_Pragma("once");

#include <vector>

#include "KeypadListener.h"
#include "Keypad.h"
#include "SingletonTemplate.h"
#include "BasePage.h"
#include "common.h"
#include "WithPoolWorkable.h"

/**
 * 页面统一管理类
 *
 * @author lizaibing
 */

class LoopStatusControlPage;
class PasswordPage;

class Authenticator;

class GuiContext :public KeypadListener, public WorkerBase {
public:
    static constexpr int PAGE_INDEX_INVALID = -1;
    static constexpr int REFRESH_PERIOD = 500 * 1000;
    static constexpr int AFTER_CALLBACK_REFRESH_PERIOD = 40 * 1000;

    using Base = KeypadListener;



    friend class SingletonTemplate<GuiContext>;

    void refreshPage();

    bool initial() {
        return true;
    }

    bool uninitial() {
        return true;
    }



    /**
     * 按键监听,包括上下页翻页的处理
     @return 0代表没有处理,1代表已处理，2 代表已处理，需要要刷新
     */
    int onKeyPressed(const KeyCode& keyCode) override;



    bool processPoolItem(WorkerBase::PointType element) {
        bool result = true;
        TaskType_t taskType = std::get<TaskType_t>(*element);
        //void* p = nullptr;

        try {
            switch(taskType) {
            case TaskType_t::DEFAULT_DATA: {
                const KeyCode keyCode = static_cast<const KeyCode>(reinterpret_cast<uintptr_t> (std::get<void*>(*element)));//

                onKeyPressed(keyCode);
                delete element;
            }
            break;


            case TaskType_t::CALLBACK: {
                mTimeout = AFTER_CALLBACK_REFRESH_PERIOD;//
                ObjectFunction* pFunction = static_cast<ObjectFunction*> (std::get<void*>(*element));  //
                (*pFunction)();
            }
            break;

            default:
                break;
            }
        } catch (std::system_error& systemError) {
            LOG_ERROR(systemError.what());
        } catch (std::exception& systemError) {
            LOG_ERROR(systemError.what());
        }

        return result;
    }


    void setPage(const int pageIndex) {
        if (pageIndex >= (int)pageList.size() || pageIndex < 0) {
            LOG_ERROR("pageIndex out of size");
            return;
        }
        if (pageIndex == currentPageNo) {
            pActivePage->refreshPage();
        } else {
            if (nullptr != pActivePage) {
                pActivePage->setVisible(false);
            }
            currentPageNo = pageIndex;
            pActivePage = pageList[currentPageNo];
            pActivePage->setVisible(true);
        }
    }



    int onKeyUp(const KeyCode& keyCode) override {
        if (currentPageNo <= 0) {
            setPage(pageList.size() - 1);
        } else {
            setPage(currentPageNo - 1);
        }
        return 2;
    }


    int onKeyDown(const KeyCode& keyCode) override {
        setPage((currentPageNo + 1 )%pageList.size());
        return 2;
    }

    int onKeySet(const KeyCode& keyCode) override {
        return 0;
    }

    int onKeyEnt(const KeyCode& keyCode) override {
        return 0;
    }

    int onOtherKey(const KeyCode& keyCode) override {
        return 0;
    }

    void run();

    ~GuiContext() {

    }



    std::vector<BasePageSharedPtr> pageList;
    LoopStatusControlPage* pLoopStatusControlPage;
    PasswordPage* pPasswordPage = nullptr;
protected:

    volatile int currentPageNo = PAGE_INDEX_INVALID;
    BasePageSharedPtr pActivePage;

    WorkerBase::PoolType pool;
    ObjectFunction refreshPageFunction;

    Authenticator& mauthenticator;

    private:
      GuiContext() ;
};


using GuiContextSingleton = SingletonTemplate<GuiContext>;


